package com.framework.utils.pay.yunzhanghujiesuan;

import com.alibaba.fastjson.JSONObject;
import com.framework.entity.sys.SysBank;
import com.framework.entity.sys.SysPayment;
import com.framework.exception.RRException;
import com.framework.utils.pay.yunzhanghujiesuan.bean.YunjiesuanPayBean;
import com.framework.utils.pay.yunzhanghujiesuan.bean.YunjiesuanQueryAmountBean;
import com.framework.utils.pay.yunzhanghujiesuan.bean.YunjiesuanQueryBean;
import com.framework.utils.string.StringUtil;
import com.google.gson.Gson;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import static com.framework.utils.HmacSha256.sha256HMAC;

/**
 * 云账户结算支付类
 */
public class YunJieSuanPay {

    //代征主体
    private static final String broker_id = "yiyun73";
    //接口基础地址
    private static final String baseURL = "https://api-jiesuan.yunzhanghu.com/";


    /**
     * 云结算转账类
     *
     * @param orderNo    订单号
     * @param bank       银行信息
     * @param identity   身份证
     * @param tranAmount 转账金额
     *  desKey     des加密码，数据库中存为公钥
     *  appkey     appkey ，数据库中存为私钥
     *  dealer_id 数据库存为 clientId
     * @param payRemark  支付备注
     */
    public static void yunJieSuanPay(String orderNo, SysBank bank, String identity, String tranAmount, SysPayment payment,String payRemark){
        //拼接json字符串，传递银行卡打款的必要信息
        //String jsonStr="{\"order_id\":"+orderNo+",\"dealer_id\":"+dealer_id+",\"broker_id\":"+broker_id+",\"real_name\":"+bank.getCardName()+"," +
        //"\"card_no\":"+bank.getBankNo()+",\"id_card\":"+identity+",\"pay\":"+tranAmount+"}";

        //创建付款对像存储,传递银行卡打款信息
        YunjiesuanPayBean bean = new YunjiesuanPayBean();
        bean.setOrder_id(orderNo);
        bean.setDealer_id(payment.getClientId());
        bean.setBroker_id(broker_id);
        bean.setReal_name(bank.getCardName());
        bean.setCard_no(bank.getBankNo());
        bean.setId_card(identity);
        bean.setPay(tranAmount);
        bean.setPay_remark(payRemark);
        bean.setNotes(payRemark);
        String jsonStr = JSONObject.toJSONString(bean);
        //拼接打款路径
        String payUrl = baseURL + "api/payment/v1/order-realtime";
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response=null;
        Map<String,Object> resultMap;
        try {
            //加密参数
            byte[] enc = YunJieSuanEncrypt.TripleDesEncrypt(jsonStr.getBytes(StandardCharsets.UTF_8), payment.getPublicKey().getBytes(StandardCharsets.UTF_8));
            byte[] enc64 = Base64.encodeBase64(enc);
            // 格式
            //随机数
            String param = "data=" + new String(enc64);
            param += "&mess=" + orderNo;
            //得到精确到秒时间戳
            String timestamp = String.valueOf(System.currentTimeMillis());
            timestamp = timestamp.substring(0, timestamp.length() - 3);
            //拼接
            param += "&timestamp=" + timestamp;
            //拼接签名
            String signmessage = param;
            param += "&sign=";
            signmessage += "&key=" + payment.getPrivateKey();
            //生成签名
            String sign = sha256HMAC(signmessage,payment.getPrivateKey());

            // 将参数输出到连接
            String body = null;
            HttpEntity entity1 = null;
            List<NameValuePair> list = new LinkedList<>();
            BasicNameValuePair param1 = new BasicNameValuePair("data", new String(enc64));
            BasicNameValuePair param2 = new BasicNameValuePair("mess", orderNo);
            BasicNameValuePair param3 = new BasicNameValuePair("timestamp", timestamp);
            BasicNameValuePair param4 = new BasicNameValuePair("sign", sign);
            BasicNameValuePair param5 = new BasicNameValuePair("sign_type", "sha256");
            list.add(param1);
            list.add(param2);
            list.add(param3);
            list.add(param4);
            list.add(param5);

            HttpPost post = new HttpPost(payUrl);
            //StringEntity entity = new StringEntity(param, "UTF-8");

            UrlEncodedFormEntity entityParam = new UrlEncodedFormEntity(list, "UTF-8");
            System.out.println(entityParam);
            post.setEntity(entityParam);
            post.addHeader("User-Agent", "Mozilla/5.0 (Windows;  U; Windows NT 5.1; en-US; rv:1.7.6)");
            post.addHeader("Content-Type", "application/x-www-form-urlencoded");
            post.addHeader("dealer-id", payment.getClientId());
            post.addHeader("request-id", String.valueOf(System.currentTimeMillis()));

            //logger.info("post:" + post);

            response = httpClient.execute(post);

            entity1 = response.getEntity();
            body = EntityUtils.toString(entity1, "UTF-8");

            if (body != null) {
                Gson gson = new Gson();
                resultMap = gson.fromJson(body, Map.class);
                String code=resultMap.get("code").toString();
                if("2006".equals(code)){
                    throw new RRException("9000","银行卡号错误");
                }else if("2027".equals(code)){
                    throw new RRException("9000","当前提现人数过多请稍后再试");
                }else  if(!"0000".equals(code)){
                    throw new RRException("9000",resultMap.get("message").toString());
                }

            }
        }catch (ClientProtocolException e) {
            System.err.println("Http协议出现问题");
            e.printStackTrace();
        } catch (ParseException e) {
            System.err.println("解析错误");
            e.printStackTrace();
        } catch (IOException e) {
            System.err.println("IO异常");
            e.printStackTrace();
        } catch (Exception e) {
            throw new RRException("9000",e.getMessage());
        } finally {
            try {
                httpClient.close();
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
    //查询云账户余额，如果不足则返回对应提示
    public static Boolean queryAccountAmount(String tranAmount, SysPayment payment) {
        YunjiesuanQueryAmountBean amountBean=new YunjiesuanQueryAmountBean();

        amountBean.setDealer_id(payment.getClientId());
        String jsonStr = JSONObject.toJSONString(amountBean);

        String url=baseURL+"api/payment/v1/query-accounts";
        try {
            byte[] enc = YunJieSuanEncrypt.TripleDesEncrypt(jsonStr.getBytes(StandardCharsets.UTF_8), payment.getPublicKey().getBytes(StandardCharsets.UTF_8));
            byte[] enc64 = Base64.encodeBase64(enc);
            // 格式
            String param = "data=" + new String(enc64);
            String mess=StringUtil.getDateString(1);
            param += "&mess=" +mess ;
            //得到精确到秒时间戳
            String timestamp = String.valueOf(System.currentTimeMillis());
            timestamp = timestamp.substring(0, timestamp.length() - 3);
            //拼接
            param += "&timestamp=" + timestamp;
            //拼接签名
            String signmessage = param;

            signmessage += "&key=" + payment.getPrivateKey();
            //生成签名
            System.out.println(signmessage);

            String sign = sha256HMAC(signmessage,payment.getPrivateKey());

            Map<String,Object> resultMap;
            // 获取连接客户端工具
            CloseableHttpClient httpClient = HttpClients.createDefault();

            String entityStr;
            CloseableHttpResponse response = null;
            try {
                /*
                 * 由于GET请求的参数都是拼装在URL地址后方，所以我们要构建一个URL，带参数
                 */
                URIBuilder uriBuilder = new URIBuilder(url);

                List<NameValuePair> list = new LinkedList<>();
                BasicNameValuePair param1 = new BasicNameValuePair("data", new String(enc64));
                BasicNameValuePair param2 = new BasicNameValuePair("mess", mess);
                BasicNameValuePair param3 = new BasicNameValuePair("timestamp",timestamp );
                BasicNameValuePair param4 = new BasicNameValuePair("sign",sign );
                BasicNameValuePair param5 = new BasicNameValuePair("sign_type", "sha256");
                list.add(param1);
                list.add(param2);
                list.add(param3);
                list.add(param4);
                list.add(param5);
                uriBuilder.setParameters(list);
                // 根据带参数的URI对象构建GET请求对象
                HttpGet httpGet = new HttpGet(uriBuilder.build());

                /*
                 * 添加请求头信息
                 */
                // 浏览器表示

                httpGet.addHeader("dealer-id", payment.getClientId());
                httpGet.addHeader("request-id", String.valueOf(System.currentTimeMillis()));

                // 执行请求
                response = httpClient.execute(httpGet);
                // 获得响应的实体对象
                HttpEntity entity = response.getEntity();
                // 使用Apache提供的工具类进行转换成字符串
                entityStr = EntityUtils.toString(entity, "UTF-8");

                if (entityStr != null) {
                    Gson gson = new Gson();
                    resultMap = gson.fromJson(entityStr, Map.class);
                    System.out.println(resultMap);
                    BigDecimal totalBalance=new BigDecimal("0.00");
                    if ("0000".equals(resultMap.get("code"))){
                        Map<String,Object> map= (Map<String, Object>) resultMap.get("data");
                        List infoslist= (List) map.get("dealer_infos");
                        for (int i = 0; i < infoslist.size(); i++) {
                            Map<String,Object> objectMap= (Map<String, Object>) infoslist.get(i);
                            if (objectMap.get("broker_id").equals(broker_id)){
                                totalBalance=totalBalance.add(new BigDecimal(objectMap.get("alipay_balance").toString()));
                                totalBalance=totalBalance.add(new BigDecimal(objectMap.get("bank_card_balance").toString()));
                                totalBalance=totalBalance.add(new BigDecimal(objectMap.get("wxpay_balance").toString()));
                            }
                        }
                        return new BigDecimal(tranAmount).compareTo(totalBalance)==1;
                    }else {

                        throw  new RRException("9000","系统异常");
                    }

                } else {
                    throw  new RRException("9000","系统异常");
                }
            } catch (Exception e) {
               throw new RRException("9000",e.getMessage());
            }finally {
                try {
                    httpClient.close();
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }catch (Exception e){
            throw new RRException("9000",e.getMessage());
        }
    }

    /**
     * 查询订单
     *
     * @param orderNo
     *  appkey
     *  desKey
     */
    public static Map<String, Object> queryOrder(String orderNo, SysPayment payment) throws Exception {
      //  String jsonStr = "{\"order_id\":" + orderNo + ",\"channel\":\"银行卡\"}";
        YunjiesuanQueryBean bean=new YunjiesuanQueryBean();
        bean.setOrder_id(orderNo);
        bean.setChannel("银行卡");
        String jsonStr = JSONObject.toJSONString(bean);
        byte[] enc = YunJieSuanEncrypt.TripleDesEncrypt(jsonStr.getBytes(StandardCharsets.UTF_8), payment.getPublicKey().getBytes(StandardCharsets.UTF_8));
        byte[] enc64 = Base64.encodeBase64(enc);
        // 格式
        String param = "data=" + new String(enc64);

        param += "&mess=" +orderNo ;
        //得到精确到秒时间戳
        String timestamp = String.valueOf(System.currentTimeMillis());
        timestamp = timestamp.substring(0, timestamp.length() - 3);
        //拼接
        param += "&timestamp=" + timestamp;
        //拼接签名
        String signmessage = param;

        //生成签名
        signmessage += "&key=" + payment.getPrivateKey();

        String sign = sha256HMAC(signmessage,payment.getPrivateKey());

        String queryUrl = baseURL + "api/payment/v1/query-realtime-order";

        Map<String,Object> resultMap=null;
        // 获取连接客户端工具
        CloseableHttpClient httpClient = HttpClients.createDefault();

        String entityStr;
        CloseableHttpResponse response = null;
        try {
            /*
             * 由于GET请求的参数都是拼装在URL地址后方，所以我们要构建一个URL，带参数
             */
            URIBuilder uriBuilder = new URIBuilder(queryUrl);
            /** 第一种添加参数的形式 */
            /*uriBuilder.addParameter("name", "root");
            uriBuilder.addParameter("password", "123456");*/
            /** 第二种添加参数的形式 */
            List<NameValuePair> list = new LinkedList<>();
            BasicNameValuePair param1 = new BasicNameValuePair("data", new String(enc64));
            BasicNameValuePair param2 = new BasicNameValuePair("mess", orderNo);
            BasicNameValuePair param3 = new BasicNameValuePair("timestamp",timestamp );
            BasicNameValuePair param4 = new BasicNameValuePair("sign",sign );
            BasicNameValuePair param5 = new BasicNameValuePair("sign_type", "sha256");
            list.add(param1);
            list.add(param2);
            list.add(param3);
            list.add(param4);
            list.add(param5);
            uriBuilder.setParameters(list);
            // 根据带参数的URI对象构建GET请求对象
            HttpGet httpGet = new HttpGet(uriBuilder.build());

            /*
             * 添加请求头信息
             */
            // 浏览器表示
            /*httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)");
            // 传输的类型
            httpGet.addHeader("Content-Type", "application/json");*/
            httpGet.addHeader("dealer-id", payment.getClientId());
            httpGet.addHeader("request-id", String.valueOf(System.currentTimeMillis()));

            // 执行请求
            response = httpClient.execute(httpGet);
            // 获得响应的实体对象
            HttpEntity entity = response.getEntity();
            // 使用Apache提供的工具类进行转换成字符串
            entityStr = EntityUtils.toString(entity, "UTF-8");

           if (entityStr != null) {
                Gson gson = new Gson();
                resultMap = gson.fromJson(entityStr, Map.class);
                return resultMap;

            } else {
                return null;
            }

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                httpClient.close();
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        return resultMap;
    }





}
